#include <fmt/format.h>
#include <fmt/ranges.h>
#include <fmt/chrono.h>
#include <fmt/os.h>
#include <iostream>
#include <string>
#include <vector>

#define PRINTLN(...) std::cout << __VA_ARGS__ << std::endl
#define INFOLN(...) std::cout << fmt::format(__VA_ARGS__) << std::endl
#define ERRORLN(...) std::cerr << fmt::format(__VA_ARGS__) << std::endl

struct date {
    int year, month, day;
};

template<>
struct fmt::formatter<date> {
    template<typename ParseContext>
    constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }

    template<typename FormatContext>
    auto format(const date &d, FormatContext &ctx) {
        return format_to(ctx.out(), "{}-{}-{:02d}", d.year, d.month, d.day);
    }
};

int main() {
    int a = 1;
    double b = 2.2;
    std::string c = "string";
    std::vector<int> d = {1, 2, 3};

    INFOLN("test int: {}", a);
    INFOLN("test int: {}", 1);
    INFOLN("test double: {}", b);
    INFOLN("test double: {}", 2.2);
    INFOLN("test string: {}", c);
    INFOLN("test string: {}", "string");
    ERRORLN("test vector: {}", d);
    ERRORLN(fmt::to_string(42));

    fmt::print("The date is {}\n", date{2012, 12, 9});

    using namespace std::literals::chrono_literals;
    fmt::print("Default format: {} {}\n", 42s, 100ms);
    fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);

    auto out = fmt::output_file("guide.log");
    out.print("Don't {}", "Panic");
}